home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / vim / src / amiga.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  32KB  |  1,530 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /*
  10.  * amiga.c
  11.  *
  12.  * Amiga system-dependent routines.
  13.  */
  14.  
  15. #include "vim.h"
  16. #include "globals.h"
  17. #include "proto.h"
  18. #include "param.h"
  19.  
  20. #include <fcntl.h>
  21.  
  22. #undef TRUE             /* will be redefined by exec/types.h */
  23. #undef FALSE
  24.  
  25. #ifndef LATTICE
  26. # include <exec/types.h>
  27. # include <exec/exec.h>
  28. # include <libraries/dos.h>
  29. # include <libraries/dosextens.h>
  30. # include <intuition/intuition.h>
  31. #else
  32. # include <proto/dos.h>
  33. # include <libraries/dosextens.h>
  34. # include <proto/intuition.h>
  35. # include <proto/exec.h>
  36. #endif
  37.  
  38. #include <exec/memory.h>
  39.  
  40. #ifndef NO_ARP
  41. #include <libraries/arpbase.h>        /* for arp.library */
  42. #endif
  43. #include <dos/dostags.h>            /* for 2.0 functions */
  44. #include <dos/dosasl.h>
  45.  
  46. #if defined(LATTICE) && !defined(SASC) && !defined(NO_ARP)
  47. # include <libraries/arp_pragmas.h>
  48. #endif
  49.  
  50. /*
  51.  * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
  52.  */
  53. #undef TRUE
  54. #define TRUE (1)
  55. #undef FALSE
  56. #define FALSE (0)
  57.  
  58. #ifndef AZTEC_C
  59. static long dos_packet __ARGS((struct MsgPort *, long, long));
  60. #endif
  61. static int lock2name __ARGS((BPTR lock, char_u *buf, long    len));
  62. static struct FileInfoBlock *get_fib __ARGS((char_u *));
  63. static int sortcmp __ARGS((char **a, char **b));
  64.  
  65. static BPTR                raw_in = (BPTR)NULL;
  66. static BPTR                raw_out = (BPTR)NULL;
  67. static int                close_win = FALSE;    /* set if Vim opened the window */
  68.  
  69. struct IntuitionBase    *IntuitionBase = NULL;
  70. #ifndef NO_ARP
  71. struct ArpBase            *ArpBase = NULL;
  72. #endif
  73.  
  74. static struct Window    *wb_window;
  75. static char_u            *oldwindowtitle = NULL;
  76.  
  77. #ifndef NO_ARP
  78. int                        dos2 = FALSE;        /* Amiga DOS 2.0x or higher */
  79. #endif
  80. int                        size_set = FALSE;    /* set to TRUE if window size was set */
  81.  
  82.     void
  83. win_resize_on()
  84. {
  85.     OUTSTRN("\033[12{");
  86. }
  87.  
  88.     void
  89. win_resize_off()
  90. {
  91.     OUTSTRN("\033[12}");
  92. }
  93.  
  94.     void
  95. mch_write(p, len)
  96.     char_u    *p;
  97.     int        len;
  98. {
  99.     Write(raw_out, (char *)p, (long)len);
  100. }
  101.  
  102. /*
  103.  * GetChars(): low level input funcion.
  104.  * Get a characters from the keyboard.
  105.  * If time == 0 do not wait for characters.
  106.  * If time == n wait a short time for characters.
  107.  * If time == -1 wait forever for characters.
  108.  *
  109.  * Return number of characters read.
  110.  */
  111.     int
  112. GetChars(buf, maxlen, time)
  113.     char_u    *buf;
  114.     int        maxlen;
  115.     int        time;                /* milli seconds */
  116. {
  117.     int        len;
  118.     long    utime;
  119.     
  120.     if (time >= 0)
  121.     {
  122.         if (time == 0)
  123.             utime = 100L;            /* time = 0 causes problems in DOS 1.2 */
  124.         else
  125.             utime = time * 1000L;    /* convert from milli to micro secs */
  126.         if (WaitForChar(raw_in, utime) == 0)    /* no character available */
  127.             return 0;
  128.     }
  129.     else    /* time == -1 */
  130.     {
  131.     /*
  132.      * If there is no character available within 2 seconds (default)
  133.      * write the autoscript file to disk
  134.      */
  135.         if (WaitForChar(raw_in, p_ut * 1000L) == 0)
  136.             updatescript(0);
  137.     }
  138.  
  139.     for (;;)        /* repeat until we got a character */
  140.     {
  141.         len = Read(raw_in, (char *)buf, (long)maxlen);
  142.         if (len > 0)
  143.             return len;
  144.     }
  145. }
  146.  
  147. /*
  148.  * return non-zero if a character is available
  149.  */
  150.     int
  151. mch_char_avail()
  152. {
  153.     return (WaitForChar(raw_in, 100L) != 0);
  154. }
  155.  
  156.     void
  157. sleep(n)
  158.     int             n;
  159. {
  160. #ifndef LATTICE            /* SAS declares void Delay(UNLONG) */
  161.     void            Delay __ARGS((long));
  162. #endif
  163.  
  164.     if (n > 0)
  165.         Delay((long)(50L * n));
  166. }
  167.  
  168.     long
  169. mch_avail_mem(special)
  170.     int        special;
  171. {
  172.     return (long)AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY);
  173. }
  174.  
  175.     void
  176. vim_delay()
  177. {
  178.     Delay(25L);
  179. }
  180.  
  181. /*
  182.  * We have no job control, fake it by starting a new shell.
  183.  */
  184. void
  185. mch_suspend()
  186. {
  187.     OUTSTR("new shell started\n");
  188.     (void)call_shell(NULL, 0, TRUE);
  189. }
  190.  
  191. #define DOS_LIBRARY     ((UBYTE *) "dos.library")
  192.  
  193.     void
  194. mch_windinit()
  195. {
  196.     static char        intlibname[] = "intuition.library";
  197.  
  198. #ifdef AZTEC_C
  199.     Enable_Abort = 0;            /* disallow vim to be aborted */
  200. #endif
  201.     Columns = 80;
  202.     Rows = 24;
  203.  
  204.     /*
  205.      * Set input and output channels, unless we have opened our own window
  206.      */
  207.     if (raw_in == (BPTR)NULL)
  208.     {
  209.         raw_in = Input();
  210.         raw_out = Output();
  211.     }
  212.  
  213.     flushbuf();
  214.  
  215.     wb_window = NULL;
  216.     if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
  217.     {
  218.         fprintf(stderr, "cannot open %s!?\n", intlibname);
  219.         mch_windexit(3);
  220.     }
  221.     (void)mch_get_winsize();
  222. }
  223.  
  224. #include <workbench/startup.h>
  225.  
  226. /*
  227.  * Check_win checks whether we have an interactive window.
  228.  * If not, a new window is opened with the newcli command.
  229.  * If we would open a window ourselves, the :sh and :! commands would not
  230.  * work properly (Why? probably because we are then running in a background CLI).
  231.  * This also is the best way to assure proper working in a next Workbench release.
  232.  *
  233.  * For the -e option (quickfix mode) and -x we open our own window and disable :sh.
  234.  * Otherwise the compiler would never know when editing is finished.
  235.  */
  236. #define BUF2SIZE 320        /* lenght of buffer for argument with complete path */
  237.  
  238.     void
  239. check_win(argc, argv)
  240.     int argc;
  241.     char **argv;
  242. {
  243.     int                i;
  244.     BPTR            nilfh, fh;
  245.     char_u            buf1[20];
  246.     char_u            buf2[BUF2SIZE];
  247.     static char_u    *(constrings[3]) = {(char_u *)"con:0/0/662/210/",
  248.                                       (char_u *)"con:0/0/640/200/",
  249.                                       (char_u *)"con:0/0/320/200/"};
  250.     static char_u    winerr[] = "VIM: Can't open window!\n";
  251.     struct WBArg    *argp;
  252.     int                ac;
  253.     char            *av;
  254.     char_u            *device = NULL;
  255.     int                exitval = 4;
  256.     struct Library    *DosBase;
  257.     int                usewin = FALSE;
  258.  
  259. /*
  260.  * check if we are running under DOS 2.0x or higher
  261.  */
  262.     if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
  263.     {
  264.         CloseLibrary(DosBase);
  265. #ifndef NO_ARP
  266.         dos2 = TRUE;
  267. #endif
  268.     }
  269.     else            /* without arp functions we NEED 2.0 */
  270.     {
  271. #ifdef NO_ARP
  272.         fprintf(stderr, "Need Amigados version 2.04 or later\n");
  273.         exit(3);
  274. #else
  275.                     /* need arp functions for dos 1.x */
  276.         if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
  277.         {
  278.             fprintf(stderr, "Need %s version %ld\n", ArpName, ArpVersion);
  279.             exit(3);
  280.         }
  281. #endif
  282.     }
  283.  
  284. /*
  285.  * scan argv[] for the '-e', '-x' and '-d' arguments
  286.  */
  287.     for (i = 1; i < argc; ++i)
  288.         if (argv[i][0] == '-')
  289.         {
  290.             switch (argv[i][1])
  291.             {
  292.             case 'e':
  293.             case 'x':
  294.                 usewin = TRUE;
  295.                 break;
  296.  
  297.             case 'd':
  298.                 if (i < argc - 1)
  299.                     device = (char_u *)argv[i + 1];
  300.                 break;
  301.             }
  302.         }
  303.  
  304. /*
  305.  * If we were not started from workbench, do not have a '-d' argument and
  306.  * we have been started with an interactive window, use that window.
  307.  */
  308.     if (argc != 0 && device == NULL &&
  309.                 IsInteractive(Input()) && IsInteractive(Output()))
  310.         return;
  311.  
  312. /*
  313.  * If we are in quickfix mode, we open our own window. We can't use the
  314.  * newcli trick below, because the compiler would not know when we are finished.
  315.  * We do the same with the '-x' option, for mail, rn, etc.
  316.  */
  317.     if (usewin)
  318.     {
  319.         /*
  320.          * Try to open a window. First try the specified device.
  321.          * Then try a 24 line 80 column window.
  322.          * If that fails, try two smaller ones.
  323.          */
  324.         for (i = -1; i < 3; ++i)
  325.         {
  326.             if (i >= 0)
  327.                 device = constrings[i];
  328.             if (device && (raw_in = Open((UBYTE *)device, (long)MODE_NEWFILE)) != (BPTR)NULL)
  329.                 break;
  330.         }
  331.         if (raw_in == (BPTR)NULL)        /* all three failed */
  332.         {
  333.             fprintf(stderr, (char *)winerr);
  334.             goto exit;
  335.         }
  336.         raw_out = raw_in;
  337.         close_win = TRUE;
  338.         return;
  339.     }
  340.  
  341.     if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
  342.     {
  343.         fprintf(stderr, "Cannot open NIL:\n");
  344.         goto exit;
  345.     }
  346.  
  347.     /*
  348.      * make a unique name for the temp file (which we will not delete!)
  349.      */
  350.     sprintf((char *)buf1, "t:nc%ld", (char *)buf1);    /* nobody else is using our stack */
  351.     if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
  352.     {
  353.         fprintf(stderr, "Cannot create %s\n", (char *)buf1);
  354.         goto exit;
  355.     }
  356.     /*
  357.      * Write the command into the file, put quotes around the arguments that
  358.      * have a space in them.
  359.      */
  360.     if (argc == 0)        /* run from workbench */
  361.         ac = ((struct WBStartup *)argv)->sm_NumArgs;
  362.     else
  363.         ac = argc;
  364.     for (i = 0; i < ac; ++i)
  365.     {
  366.         if (argc == 0)
  367.         {
  368.             *buf2 = NUL;
  369.             argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
  370.             if (argp->wa_Lock)
  371.                 (void)lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
  372. #ifndef NO_ARP
  373.             if (dos2)        /* use 2.0 function */
  374. #endif
  375.                 AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
  376. #ifndef NO_ARP
  377.             else            /* use arp function */
  378.                 TackOn((char *)buf2, argp->wa_Name);
  379. #endif
  380.             av = (char *)buf2;
  381.         }
  382.         else
  383.             av = argv[i];
  384.  
  385.         if (av[0] == '-' && av[1] == 'd')        /* skip '-d' option */
  386.         {
  387.             ++i;
  388.             continue;
  389.         }
  390.         if (strchr(av, ' '))
  391.             Write(fh, "\"", 1L);
  392.         Write(fh, av, (long)strlen(av));
  393.         if (strchr(av, ' '))
  394.             Write(fh, "\"", 1L);
  395.         Write(fh, " ", 1L);
  396.     }
  397.     Write(fh, "\nendcli\n", 8L);
  398.     Close(fh);
  399.  
  400. /*
  401.  * Try to open a new cli in a window. If '-d' argument was given try to open
  402.  * the specified device. Then try a 24 line 80 column window.
  403.  * If that fails, try two smaller ones.
  404.  */
  405.     for (i = -1; i < 3; ++i)
  406.     {
  407.         if (i >= 0)
  408.             device = constrings[i];
  409.         else if (device == NULL)
  410.             continue;
  411.         sprintf((char *)buf2, "newcli <nil: >nil: %s from %s", (char *)device, (char *)buf1);
  412. #ifndef NO_ARP
  413.         if (dos2)
  414.         {
  415. #endif
  416.             if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
  417.                 break;
  418. #ifndef NO_ARP
  419.         }
  420.         else
  421.         {
  422.             if (Execute((UBYTE *)buf2, nilfh, nilfh))
  423.                 break;
  424.         }
  425. #endif
  426.     }
  427.     if (i == 3)        /* all three failed */
  428.     {
  429.         DeleteFile((UBYTE *)buf1);
  430.         fprintf(stderr, (char *)winerr);
  431.         goto exit;
  432.     }
  433.     exitval = 0;    /* The Execute succeeded: exit this program */
  434.  
  435. exit:
  436. #ifndef NO_ARP
  437.     if (ArpBase)
  438.         CloseLibrary((struct Library *) ArpBase);
  439. #endif
  440.     exit(exitval);
  441. }
  442.  
  443. /*
  444.  * fname_case(): Set the case of the filename, if it already exists.
  445.  *                 This will cause the filename to remain exactly the same.
  446.  */
  447.     void
  448. fname_case(name)
  449.     char_u    *name;
  450. {
  451.     register struct FileInfoBlock    *fib;
  452.     register size_t                    len;
  453.  
  454.     fib = get_fib(name);
  455.     if (fib != NULL)
  456.     {
  457.         len = STRLEN(name);
  458.         if (len == strlen(fib->fib_FileName))    /* safety check */
  459.             memmove((char *)name, fib->fib_FileName, len);
  460.         free(fib);
  461.     }
  462. }
  463.  
  464. /*
  465.  * Get the FileInfoBlock for file "fname"
  466.  * The returned structure has to be free()d.
  467.  * Returns NULL on error.
  468.  */
  469.     static struct FileInfoBlock *
  470. get_fib(fname)
  471.     char_u *fname;
  472. {
  473.     register BPTR                    flock;
  474.     register struct FileInfoBlock    *fib;
  475.  
  476.     if (fname == NULL)        /* safety check */
  477.         return NULL;
  478.     fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
  479.     if (fib != NULL)
  480.     {
  481.         flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  482.         if (flock == (BPTR)NULL || !Examine(flock, fib))
  483.         {
  484.             free(fib);    /* in case of an error the memory is freed here */
  485.             fib = NULL;
  486.         }
  487.         if (flock)
  488.             UnLock(flock);
  489.     }
  490.     return fib;
  491. }
  492.  
  493. /*
  494.  * set the title of our window
  495.  * icon name is not set
  496.  */
  497.     void
  498. mch_settitle(title, icon)
  499.     char_u    *title;
  500.     char_u    *icon;
  501. {
  502.     if (wb_window != NULL && title != NULL)
  503.         SetWindowTitles(wb_window, (UBYTE *)title, (UBYTE *)-1L);
  504. }
  505.  
  506. /*
  507.  * Restore the window/icon title.
  508.  * which is one of:
  509.  *    1  Just restore title
  510.  *  2  Just restore icon (which we don't have)
  511.  *    3  Restore title and icon (which we don't have)
  512.  */
  513.     void
  514. mch_restore_title(which)
  515.     int which;
  516. {
  517.     mch_settitle((which & 1) ? oldwindowtitle : NULL, NULL);
  518. }
  519.  
  520. /*
  521.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  522.  * Return OK for success, FAIL for failure.
  523.  */
  524.     int
  525. vim_dirname(buf, len)
  526.     char_u        *buf;
  527.     int            len;
  528. {
  529.     return FullName((char_u *)"", buf, len);
  530. }
  531.  
  532. /*
  533.  * get absolute filename into buffer 'buf' of length 'len' bytes
  534.  *
  535.  * return FAIL for failure, OK otherwise
  536.  */
  537.     int
  538. FullName(fname, buf, len)
  539.     char_u        *fname, *buf;
  540.     int            len;
  541. {
  542.     BPTR        l;
  543.     int            retval = FAIL;
  544.     int            i;
  545.  
  546.     *buf = NUL;
  547.     if (fname == NULL)    /* always fail */
  548.         return FAIL;
  549.  
  550.     if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)) != (BPTR)0)/* lock the file */
  551.     {
  552.         retval = lock2name(l, buf, (long)len);
  553.         UnLock(l);
  554.     }
  555.     else if (!isFullName(fname))        /* not a full path yet */
  556.     {
  557.         /*
  558.          * if cannot lock the file, try to lock the current directory and then
  559.          * concatenate the file name
  560.          */
  561.         if ((l = Lock((UBYTE *)"", (long)ACCESS_READ)) != (BPTR)NULL) /* lock current dir */
  562.         {
  563.             retval = lock2name(l, buf, (long)len);
  564.             UnLock(l);
  565.             if (retval == OK)
  566.             {
  567.                 i = STRLEN(buf);
  568.                 if (i < len - 1 && (i == 0 || buf[i - 1] != ':'))
  569.                     buf[i++] = '/';
  570.                 STRNCPY(buf + i, fname, (size_t)(len - i));    /* concatenate the fname */
  571.             }
  572.         }
  573.     }
  574.     if (retval == FAIL || *buf == 0 || *buf == ':')
  575.         STRCPY(buf, fname);    /* something failed; use the filename */
  576.     return retval;
  577. }
  578.  
  579. /*
  580.  * return TRUE is fname is an absolute path name
  581.  */
  582.     int
  583. isFullName(fname)
  584.     char_u        *fname;
  585. {
  586.     return (STRCHR(fname, ':') != NULL);
  587. }
  588.  
  589. /*
  590.  * Get the full filename from a lock. Use 2.0 function if possible, because
  591.  * the arp function has more restrictions on the path length.
  592.  *
  593.  * return FAIL for failure, OK otherwise
  594.  */
  595.     static int
  596. lock2name(lock, buf, len)
  597.     BPTR    lock;
  598.     char_u    *buf;
  599.     long    len;
  600. {
  601. #ifndef NO_ARP
  602.     if (dos2)                /* use 2.0 function */
  603. #endif
  604.         return ((int)NameFromLock(lock, (UBYTE *)buf, len) ? OK : FAIL);
  605. #ifndef NO_ARP
  606.     else                /* use arp function */
  607.         return ((int)PathName(lock, (char *)buf, (long)(len/32)) ? OK : FAIL);
  608. #endif
  609. }
  610.  
  611. /*
  612.  * get file permissions for 'name'
  613.  */
  614.     long
  615. getperm(name)
  616.     char_u        *name;
  617. {
  618.     struct FileInfoBlock    *fib;
  619.     long                     retval = -1;
  620.  
  621.     fib = get_fib(name);
  622.     if (fib != NULL)
  623.     {
  624.         retval = fib->fib_Protection;
  625.         free(fib);
  626.     }
  627.     return retval;
  628. }
  629.  
  630. /*
  631.  * set file permission for 'name' to 'perm'
  632.  *
  633.  * return FAIL for failure, OK otherwise
  634.  */
  635.     int
  636. setperm(name, perm)
  637.     char_u        *name;
  638.     long        perm;
  639. {
  640.     perm &= ~FIBF_ARCHIVE;                /* reset archived bit */
  641.     return (SetProtection((UBYTE *)name, (long)perm) ? OK : FAIL);
  642. }
  643.  
  644. /*
  645.  * return FALSE if "name" is not a directory
  646.  * return TRUE if "name" is a directory.
  647.  * return -1 for error.
  648.  */
  649.     int
  650. isdir(name)
  651.     char_u        *name;
  652. {
  653.     struct FileInfoBlock    *fib;
  654.     int                     retval = -1;
  655.  
  656.     fib = get_fib(name);
  657.     if (fib != NULL)
  658.     {
  659.         retval = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE);
  660.         free(fib);
  661.     }
  662.     return retval;
  663. }
  664.  
  665. /*
  666.  * Careful: mch_windexit() may be called before mch_windinit()!
  667.  */
  668.     void
  669. mch_windexit(r)
  670.     int             r;
  671. {
  672.     if (raw_in)                        /* put terminal in 'normal' mode */
  673.     {
  674.         settmode(0);
  675.         stoptermcap();
  676.     }
  677.     if (raw_out)
  678.     {
  679.         if (term_console)
  680.         {
  681.             win_resize_off();        /* window resize events de-activated */
  682.             if (size_set)
  683.                 OUTSTR("\233t\233u");        /* reset window size (CSI t CSI u) */
  684.         }
  685.         flushbuf();
  686.     }
  687.  
  688.     mch_restore_title(3);            /* restore window title */
  689.  
  690.     ml_close_all();                 /* remove all memfiles */
  691.  
  692. #ifndef NO_ARP
  693.     if (ArpBase)
  694.         CloseLibrary((struct Library *) ArpBase);
  695. #endif
  696.     if (close_win)
  697.         Close(raw_in);
  698.     if (r)
  699.         printf("Vim exiting with %d\n", r);    /* somehow this makes :cq work!? */
  700.     exit(r);
  701. }
  702.  
  703. /*
  704.  * This is a routine for setting a given stream to raw or cooked mode on the
  705.  * Amiga . This is useful when you are using Lattice C to produce programs
  706.  * that want to read single characters with the "getch()" or "fgetc" call.
  707.  *
  708.  * Written : 18-Jun-87 By Chuck McManis.
  709.  */
  710.  
  711. #define MP(xx)    ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
  712.  
  713. /*
  714.  * Function mch_settmode() - Convert the specified file pointer to 'raw' or 'cooked'
  715.  * mode. This only works on TTY's.
  716.  *
  717.  * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
  718.  *        getch() will return immediately rather than wait for a return. You
  719.  *        lose editing features though.
  720.  *
  721.  * Cooked: This function returns the designate file pointer to it's normal,
  722.  *        wait for a <CR> mode. This is exactly like raw() except that
  723.  *        it sends a 0 to the console to make it back into a CON: from a RAW:
  724.  */
  725.     void
  726. mch_settmode(raw)
  727.     int            raw;
  728. {
  729.     if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE, raw ? -1L : 0L) == 0)
  730.         fprintf(stderr, "cannot change console mode ?!\n");
  731. }
  732.  
  733. /*
  734.  * set screen mode, always fails.
  735.  */
  736.     int
  737. mch_screenmode(arg)
  738.     char_u     *arg;
  739. {
  740.     EMSG("Screen mode setting not supported");
  741.     return FAIL;
  742. }
  743.  
  744. /*
  745.  * Code for this routine came from the following :
  746.  *
  747.  * ConPackets.c -  C. Scheppner, A. Finkel, P. Lindsay    CBM
  748.  *     DOS packet example
  749.  *     Requires 1.2
  750.  *
  751.  * Found on Fish Disk 56.
  752.  *
  753.  * Heavely modified by mool.
  754.  */
  755.  
  756. #include <devices/conunit.h>
  757.  
  758. /*
  759.  * try to get the real window size
  760.  * return FAIL for failure, OK otherwise
  761.  */
  762.     int
  763. mch_get_winsize()
  764. {
  765.     struct ConUnit    *conUnit;
  766.      char            id_a[sizeof(struct InfoData) + 3];
  767.     struct InfoData *id;
  768.  
  769.     if (!term_console)    /* not an amiga window */
  770.         return FAIL;
  771.  
  772.     /* insure longword alignment */
  773.      id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  774.  
  775.     /*
  776.      * Should make console aware of real window size, not the one we set.
  777.      * Unfortunately, under DOS 2.0x this redraws the window and it
  778.      * is rarely needed, so we skip it now, unless we changed the size.
  779.      */
  780.     if (size_set)
  781.         OUTSTR("\233t\233u");    /* CSI t CSI u */
  782.     flushbuf();
  783.  
  784.     if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0 ||
  785.                 (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
  786.     {
  787.         /* it's not an amiga window, maybe aux device */
  788.         /* terminal type should be set */
  789.         term_console = FALSE;
  790.         return FAIL;
  791.     }
  792.     if (oldwindowtitle == NULL)
  793.         oldwindowtitle = (char_u *)wb_window->Title;
  794.     if (id->id_InUse == (BPTR)NULL)
  795.     {
  796.         fprintf(stderr, "mch_get_winsize: not a console??\n");
  797.         return FAIL;
  798.     }
  799.     conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
  800.  
  801.     /* get window size */
  802.     Rows = conUnit->cu_YMax + 1;
  803.     Columns = conUnit->cu_XMax + 1;
  804.     if (Rows < 0 || Rows > 200)     /* cannot be an amiga window */
  805.     {
  806.         Columns = 80;
  807.         Rows = 24;
  808.         term_console = FALSE;
  809.         return FAIL;
  810.     }
  811.     check_winsize();
  812.  
  813.     return OK;
  814. }
  815.  
  816. /*
  817.  * try to set the real window size
  818.  */
  819.     void
  820. mch_set_winsize()
  821. {
  822.     if (term_console)
  823.     {
  824.         size_set = TRUE;
  825.         outchar(CSI);
  826.         outnum((long)Rows);
  827.         outchar('t');
  828.         outchar(CSI);
  829.         outnum((long)Columns);
  830.         outchar('u');
  831.         flushbuf();
  832.     }
  833. }
  834.  
  835. #ifdef SETKEYMAP
  836. /*
  837.  * load and activate a new keymap for our CLI - DOES NOT WORK -
  838.  * The problem is that after the setting of the keymap the input blocks
  839.  * But the new keymap works allright in another window.
  840.  * Tried but no improvement:
  841.  * - remembering the length, data and command fields in request->io_xxx
  842.  * - settmode(0) first, settmode(1) afterwards
  843.  * - putting the keymap directly in conunit structure
  844.  */
  845.  
  846. #include <devices/keymap.h>
  847.  
  848.     void
  849. set_keymap(name)
  850.     char_u *name;
  851. {
  852.      char                    id_a[sizeof(struct InfoData) + 3];
  853.     struct InfoData            *id;
  854.     static struct KeyMap    *old;
  855.     static BPTR                segment = (BPTR)NULL;
  856.     struct IOStdReq            *request;
  857.     int                        c;
  858.  
  859.     if (!term_console)
  860.         return;
  861.  
  862.     /* insure longword alignment */
  863.      id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  864.  
  865.     if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0)
  866.     {
  867.         EMSG("dos_packet failed");
  868.         return;
  869.     }
  870.     if (id->id_InUse == (BPTR)NULL)
  871.     {
  872.         EMSG("not a console??");
  873.         return;
  874.     }
  875.     request = (struct IOStdReq *) id->id_InUse;
  876.  
  877.     if (segment != (BPTR)NULL)    /* restore old keymap */
  878.     {
  879.         request->io_Command = CD_SETKEYMAP;
  880.         request->io_Length = sizeof(struct KeyMap);
  881.         request->io_Data = (APTR)old;
  882.         DoIO((struct IORequest *)request);
  883.         if (request->io_Error)
  884.             EMSG("Cannot reset keymap");
  885.         else                /* no error, free the allocated memory */
  886.         {
  887.             UnLoadSeg(segment);
  888.             FreeMem(old, sizeof(struct KeyMap));
  889.             segment = (BPTR)NULL;
  890.         }
  891.     }
  892.     if (name != NULL)
  893.     {
  894.         segment = LoadSeg(name);
  895.         if (segment == (BPTR)NULL)
  896.         {
  897.             EMSG("Cannot open keymap file");
  898.             return;
  899.         }
  900.         old = (struct KeyMap *)AllocMem(sizeof(struct KeyMap), MEMF_PUBLIC);
  901.         if (old == NULL)
  902.         {
  903.             EMSG(e_outofmem);
  904.             UnLoadSeg(segment);
  905.             segment = (BPTR)NULL;
  906.         }
  907.         else
  908.         {
  909.             request->io_Command = CD_ASKKEYMAP;
  910.             request->io_Length = sizeof(struct KeyMap);
  911.             request->io_Data = (APTR)old;
  912.             DoIO((struct IORequest *)request);
  913.             if (request->io_Error)
  914.             {
  915.                 EMSG("Cannot get old keymap");
  916.                 UnLoadSeg(segment);
  917.                 segment = (BPTR)NULL;
  918.                 FreeMem(old, sizeof(struct KeyMap));
  919.             }
  920.             else
  921.             {
  922.                 request->io_Command = CD_SETKEYMAP;
  923.                 request->io_Length = sizeof(struct KeyMap);
  924.                 request->io_Data = (APTR)((segment << 2) + 18);
  925.                 DoIO((struct IORequest *)request);
  926.                 if (request->io_Error)
  927.                     EMSG("Cannot set keymap");
  928.  
  929.                 /* test for blocking */
  930.                 request->io_Command = CMD_READ;
  931.                 request->io_Length = 1;
  932.                 request->io_Data = (APTR)&c;
  933.                 DoIO((struct IORequest *)request);    /* BLOCK HERE! */
  934.                 if (request->io_Error)
  935.                     EMSG("Cannot set keymap");
  936.             }
  937.         }
  938.     }
  939. }
  940. #endif
  941.  
  942. #ifndef AZTEC_C
  943. /*
  944.  * Sendpacket.c
  945.  *
  946.  * An invaluable addition to your Amiga.lib file. This code sends a packet to
  947.  * the given message port. This makes working around DOS lots easier.
  948.  *
  949.  * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
  950.  * however that you may wish to add it to Amiga.Lib, to do so, compile it and
  951.  * say 'oml lib:amiga.lib -r sendpacket.o'
  952.  */
  953.  
  954. /* #include <proto/exec.h> */
  955. /* #include <proto/dos.h> */
  956. #include <exec/memory.h>
  957.  
  958. /*
  959.  * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
  960.  * Finkel. This function will send a packet of the given type to the Message
  961.  * Port supplied.
  962.  */
  963.  
  964.     static long
  965. dos_packet(pid, action, arg)
  966.     struct MsgPort *pid;    /* process indentifier ... (handlers message port) */
  967.     long            action, /* packet type ... (what you want handler to do)   */
  968.                     arg;    /* single argument */
  969. {
  970. # ifndef NO_ARP
  971.     struct MsgPort            *replyport;
  972.     struct StandardPacket    *packet;
  973.     long                    res1;
  974.  
  975.     if (dos2)
  976. # endif
  977.         return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L);    /* use 2.0 function */
  978. # ifndef NO_ARP
  979.  
  980.     replyport = (struct MsgPort *) CreatePort(NULL, 0);    /* use arp function */
  981.     if (!replyport)
  982.         return (0);
  983.  
  984.     /* Allocate space for a packet, make it public and clear it */
  985.     packet = (struct StandardPacket *)
  986.         AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
  987.     if (!packet) {
  988.         DeletePort(replyport);
  989.         return (0);
  990.     }
  991.     packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
  992.     packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  993.     packet->sp_Pkt.dp_Port = replyport;
  994.     packet->sp_Pkt.dp_Type = action;
  995.     packet->sp_Pkt.dp_Arg1 = arg;
  996.  
  997.     PutMsg(pid, (struct Message *)packet);        /* send packet */
  998.  
  999.     WaitPort(replyport);
  1000.     GetMsg(replyport);
  1001.  
  1002.     res1 = packet->sp_Pkt.dp_Res1;
  1003.  
  1004.     FreeMem(packet, (long) sizeof(struct StandardPacket));
  1005.     DeletePort(replyport);
  1006.  
  1007.     return (res1);
  1008. # endif
  1009. }
  1010. #endif
  1011.  
  1012. /*
  1013.  * call shell, return FAIL for failure, OK otherwise
  1014.  */
  1015.     int
  1016. call_shell(cmd, filter, cooked)
  1017.     char_u    *cmd;
  1018.     int        filter;        /* if != 0: called by dofilter() */
  1019.     int        cooked;
  1020. {
  1021.     BPTR    mydir;
  1022.     int        x;
  1023. #ifndef LATTICE
  1024.     int        use_execute;
  1025.     char_u    *shellcmd = NULL;
  1026.     char_u    *shellarg;
  1027. #endif
  1028.     int    retval = OK;
  1029.  
  1030.     if (close_win)
  1031.     {
  1032.         /* if Vim opened a window: Executing a shell may cause crashes */
  1033.         EMSG("Cannot execute shell with -e or -x option");
  1034.         return FAIL;
  1035.     }
  1036.  
  1037.     if (term_console)
  1038.         win_resize_off();             /* window resize events de-activated */
  1039.     flushbuf();
  1040.  
  1041.     if (cooked)
  1042.         settmode(0);                 /* set to cooked mode */
  1043.     mydir = Lock((UBYTE *)"", (long)ACCESS_READ);    /* remember current directory */
  1044.  
  1045. #ifdef LATTICE                        /* not tested very much */
  1046.     if (cmd == NULL)
  1047.     {
  1048. # ifndef NO_ARP
  1049.         if (dos2)
  1050. # endif
  1051.             x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1052. # ifndef NO_ARP
  1053.         else
  1054.             x = Execute(p_sh, raw_in, raw_out);
  1055. # endif
  1056.     }
  1057.     else
  1058.     {
  1059. # ifndef NO_ARP
  1060.         if (dos2)
  1061. # endif
  1062.             x = SystemTags((char *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1063. # ifndef NO_ARP
  1064.         else
  1065.             x = Execute((char *)cmd, 0L, raw_out);
  1066. # endif
  1067.     }
  1068. # ifdef NO_ARP
  1069.     if (x < 0)
  1070. # else
  1071.     if ((dos2 && x < 0) || (!dos2 && !x))
  1072. # endif
  1073.     {
  1074.         outstr((char_u *)"Cannot execute ");
  1075.         if (cmd == NULL)
  1076.         {
  1077.             outstr((char_u *)"shell ");
  1078.             outstr(p_sh);
  1079.         }
  1080.         else
  1081.             outstr(cmd);
  1082.         outchar('\n');
  1083.         retval = FAIL;
  1084.     }
  1085. # ifdef NO_ARP
  1086.     else if (x)
  1087. # else
  1088.     else if (!dos2 || x)
  1089. # endif
  1090.     {
  1091.         if (x = IoErr())
  1092.         {
  1093. #ifdef WEBB_COMPLETE
  1094.             if (!expand_interactively)
  1095. #endif
  1096.             {
  1097.                 outchar('\n');
  1098.                 outnum(x);
  1099.                 outstr((char_u *)" returned\n");
  1100.             }
  1101.             retval = FAIL;
  1102.         }
  1103.     }
  1104. #else    /* !LATTICE */
  1105.     if (p_st >= 4 || (p_st >= 2 && !filter))
  1106.         use_execute = 1;
  1107.     else
  1108.         use_execute = 0;
  1109.     if (!use_execute)
  1110.     {
  1111.         /*
  1112.          * separate shell name from argument
  1113.          */
  1114.         shellcmd = strsave(p_sh);
  1115.         if (shellcmd == NULL)        /* out of memory, use Execute */
  1116.             use_execute = 1;
  1117.         else
  1118.         {
  1119.             shellarg = shellcmd;
  1120.             skiptospace(&shellarg);    /* find start of arguments */
  1121.             if (*shellarg != NUL)
  1122.             {
  1123.                 *shellarg++ = NUL;
  1124.                 skipspace(&shellarg);
  1125.             }
  1126.         }
  1127.     }
  1128.     if (cmd == NULL)
  1129.     {
  1130.         if (use_execute)
  1131.         {
  1132. # ifndef NO_ARP
  1133.             if (dos2)
  1134. # endif
  1135.                 x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1136. # ifndef NO_ARP
  1137.             else
  1138.                 x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
  1139. # endif
  1140.         }
  1141.         else
  1142.             x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, NULL);
  1143.     }
  1144.     else if (use_execute)
  1145.     {
  1146. # ifndef NO_ARP
  1147.         if (dos2)
  1148. # endif
  1149.             x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1150. # ifndef NO_ARP
  1151.         else
  1152.             x = !Execute((UBYTE *)cmd, 0L, raw_out);
  1153. # endif
  1154.     }
  1155.     else if (p_st & 1)
  1156.         x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, (char *)cmd, NULL);
  1157.     else
  1158.         x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, "-c", (char *)cmd, NULL);
  1159. # ifdef NO_ARP
  1160.     if (x < 0)
  1161. # else
  1162.     if ((dos2 && x < 0) || (!dos2 && x))
  1163. # endif
  1164.     {
  1165.         outstr((char_u *)"Cannot execute ");
  1166.         if (use_execute)
  1167.         {
  1168.             if (cmd == NULL)
  1169.                 outstr(p_sh);
  1170.             else
  1171.                 outstr(cmd);
  1172.         }
  1173.         else
  1174.         {
  1175.             outstr((char_u *)"shell ");
  1176.             outstr(shellcmd);
  1177.         }
  1178.         outchar('\n');
  1179.         retval = FAIL;
  1180.     }
  1181.     else
  1182.     {
  1183.         if (use_execute)
  1184.         {
  1185. # ifdef NO_ARP
  1186.             if (x)
  1187. # else
  1188.             if (!dos2 || x)
  1189. # endif
  1190.                 x = IoErr();
  1191.         }
  1192.         else
  1193.             x = wait();
  1194.         if (x)
  1195.         {
  1196. #ifdef WEBB_COMPLETE
  1197.             if (!expand_interactively)
  1198. #endif
  1199.             {
  1200.                 outchar('\n');
  1201.                 outnum((long)x);
  1202.                 outstrn((char_u *)" returned\n");
  1203.             }
  1204.             retval = FAIL;
  1205.         }
  1206.     }
  1207.     free(shellcmd);
  1208. #endif    /* !LATTICE */
  1209.  
  1210.     if (mydir = CurrentDir(mydir))        /* make sure we stay in the same directory */
  1211.         UnLock(mydir);
  1212.     if (cooked)
  1213.         settmode(1);                     /* set to raw mode */
  1214.     resettitle();
  1215.     if (term_console)
  1216.         win_resize_on();                 /* window resize events activated */
  1217.     return retval;
  1218. }
  1219.  
  1220. /*
  1221.  * check for an "interrupt signal"
  1222.  * We only react to a CTRL-C, but also clear the other break signals to avoid trouble
  1223.  * with lattice-c programs.
  1224.  */
  1225.     void
  1226. breakcheck()
  1227. {
  1228.    if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
  1229.         got_int = TRUE;
  1230. }
  1231.  
  1232. /* this routine causes manx to use this Chk_Abort() rather than it's own */
  1233. /* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
  1234. /* is zero).  Since we want to check for our own ^C's                    */
  1235.  
  1236. #ifdef _DCC
  1237. #define Chk_Abort chkabort
  1238. #endif
  1239.  
  1240.     long
  1241. Chk_Abort()
  1242. {
  1243.     return(0L);
  1244. }
  1245.  
  1246. /*
  1247.  * ExpandWildCard() - this code does wild-card pattern matching using the arp
  1248.  *                      routines. This is based on WildDemo2.c (found in arp1.1
  1249.  *                      distribution). That code's copyright follows :
  1250.  *-------------------------------------------------------------------------
  1251.  * WildDemo2.c - Search filesystem for patterns, and separate into directories
  1252.  *         and files, sorting each separately using DA lists.
  1253.  *
  1254.  * -+=SDB=+-
  1255.  *
  1256.  * Copyright (c) 1987, Scott Ballantyne
  1257.  * Use and abuse as you please.
  1258.  *
  1259.  * num_pat is number of input patterns
  1260.  * pat is array of pointers to input patterns
  1261.  * num_file is pointer to number of matched file names
  1262.  * file is pointer to array of pointers to matched file names
  1263.  * if file_only is TRUE we match only files, no dirs
  1264.  * if list_notfound is TRUE we include not-found entries (probably locked)
  1265.  * return OK for success, FAIL for error (you may loose some memory)
  1266.  *-------------------------------------------------------------------------
  1267.  */
  1268.  
  1269. /* #include <arpfunctions.h> */
  1270. extern void *malloc __ARGS((size_t)), *calloc __ARGS((size_t, size_t));
  1271. static int insfile __ARGS((char_u *, int));
  1272. static void freefiles __ARGS((void));
  1273.  
  1274. #define ANCHOR_BUF_SIZE (512)
  1275. #define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
  1276.  
  1277. /*
  1278.  * we use this structure to built a list of file names
  1279.  */
  1280. struct onefile
  1281. {
  1282.     struct onefile    *next;
  1283.     char_u            name[1];    /* really longer */
  1284. } *namelist = NULL;
  1285.  
  1286. /*
  1287.  * insert one file into the list of file names
  1288.  * return FAIL for failure
  1289.  * return OK for success
  1290.  */
  1291.     static int
  1292. insfile(name, isdir)
  1293.     char_u    *name;
  1294.     int        isdir;
  1295. {
  1296.     struct onefile *new;
  1297.  
  1298.     new = (struct onefile *)alloc((unsigned)(sizeof(struct onefile) + STRLEN(name) + isdir));
  1299.     if (new == NULL)
  1300.         return FAIL;
  1301.     STRCPY(&(new->name[0]), name);
  1302.     if (isdir)
  1303.         STRCAT(&(new->name[0]), "/");
  1304.     new->next = namelist;
  1305.     namelist = new;
  1306.     return OK;
  1307. }
  1308.  
  1309. /*
  1310.  * free a whole list of file names
  1311.  */
  1312.     static void
  1313. freefiles()
  1314. {
  1315.     struct onefile *p;
  1316.  
  1317.     while (namelist)
  1318.     {
  1319.         p = namelist->next;
  1320.         free(namelist);
  1321.         namelist = p;
  1322.     }
  1323. }
  1324.  
  1325.     static int
  1326. sortcmp(a, b)
  1327.     char **a, **b;
  1328. {
  1329.     return strcmp(*a, *b);
  1330. }
  1331.  
  1332.     int
  1333. ExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
  1334.     int             num_pat;
  1335.     char_u          **pat;
  1336.     int            *num_file;
  1337.     char_u         ***file;
  1338.     int            files_only;
  1339.     int            list_notfound;
  1340. {
  1341.     int                     i;
  1342.     struct AnchorPath        *Anchor;
  1343.     int                        domatchend = FALSE;
  1344.     LONG                    Result;
  1345.     struct onefile            *p;
  1346.     char_u                    *errmsg = NULL;
  1347.     char_u                    *starbuf, *sp, *dp;
  1348.     int                        foundone;
  1349.  
  1350.     *num_file = 0;
  1351.     *file = (char_u **)"";
  1352.  
  1353.     /* Get our AnchorBase */
  1354.     Anchor = (struct AnchorPath *) calloc((size_t)1, (size_t)ANCHOR_SIZE);
  1355.     if (!Anchor)
  1356.         goto OUT_OF_MEMORY;
  1357.     Anchor->ap_StrLen = ANCHOR_BUF_SIZE;    /* ap_Length not supported anymore */
  1358. #ifdef APF_DODOT
  1359.     Anchor->ap_Flags = APF_DODOT | APF_DOWILD;        /* allow '.' for current dir */
  1360. #else
  1361.     Anchor->ap_Flags = APF_DoDot | APF_DoWild;        /* allow '.' for current dir */
  1362. #endif
  1363.  
  1364.     for (i = 0; i < num_pat; i++)
  1365.     {
  1366. #ifndef NO_ARP
  1367.         if (dos2)
  1368.         {
  1369. #endif
  1370.                 /* hack to replace '*' by '#?' */
  1371.             starbuf = alloc((unsigned)(2 * STRLEN(pat[i]) + 1));    /* maximum required */
  1372.             if (starbuf == NULL)
  1373.                 goto OUT_OF_MEMORY;
  1374.             for (sp = pat[i], dp = starbuf; *sp; ++sp)
  1375.             {
  1376.                 if (*sp == '*')
  1377.                 {
  1378.                     *dp++ = '#';
  1379.                     *dp++ = '?';
  1380.                 }
  1381.                 else
  1382.                     *dp++ = *sp;
  1383.             }
  1384.             *dp = NUL;
  1385.             Result = MatchFirst((UBYTE *)starbuf, Anchor);
  1386.             free(starbuf);
  1387. #ifndef NO_ARP
  1388.         }
  1389.         else
  1390.             Result = FindFirst((char *)pat[i], Anchor);
  1391. #endif
  1392.         domatchend = TRUE;
  1393.         foundone = FALSE;
  1394.         while (Result == 0)
  1395.         {
  1396.             if (!files_only || Anchor->ap_Info.fib_DirEntryType < 0)
  1397.             {
  1398.                 (*num_file)++;
  1399.                 if (insfile((char_u *)Anchor->ap_Buf, Anchor->ap_Info.fib_DirEntryType >= 0) == FAIL)
  1400.                 {
  1401. OUT_OF_MEMORY:
  1402.                     errmsg = (char_u *)"Out of memory";
  1403.                     goto Return;
  1404.                 }
  1405.                 foundone = TRUE;
  1406.             }
  1407. #ifndef NO_ARP
  1408.             if (dos2)
  1409. #endif
  1410.                 Result = MatchNext(Anchor);
  1411. #ifndef NO_ARP
  1412.             else
  1413.                 Result = FindNext(Anchor);
  1414. #endif
  1415.         }
  1416.         if (Result == ERROR_BUFFER_OVERFLOW)
  1417.         {
  1418.             errmsg = (char_u *)"ANCHOR_BUF_SIZE too small.";
  1419.             goto Return;
  1420.         }
  1421.         if (!foundone)
  1422.         {
  1423.             if (list_notfound)    /* put object with error in list */
  1424.             {
  1425.                 (*num_file)++;
  1426.                 if (insfile(pat[i], FALSE) == FAIL)
  1427.                     goto OUT_OF_MEMORY;
  1428.             }
  1429.             else if (Result != ERROR_OBJECT_NOT_FOUND && Result != ERROR_NO_MORE_ENTRIES)
  1430.             {
  1431.                 errmsg = (char_u *)"I/O ERROR";
  1432.                 goto Return;
  1433.             }
  1434.         }
  1435. #ifndef NO_ARP
  1436.         if (dos2)
  1437. #endif
  1438.             MatchEnd(Anchor);
  1439. #ifndef NO_ARP
  1440.         else
  1441.             FreeAnchorChain(Anchor);
  1442. #endif
  1443.         domatchend = FALSE;
  1444.     }
  1445.  
  1446.     p = namelist;
  1447.     if (p)
  1448.     {
  1449.         *file = (char_u **) malloc(sizeof(char_u *) * (*num_file));
  1450.         if (*file == NULL)
  1451.             goto OUT_OF_MEMORY;
  1452.         for (i = *num_file - 1; p; p = p->next, --i)
  1453.         {
  1454.             (*file)[i] = (char_u *) malloc(STRLEN(p->name) + 1);
  1455.             if ((*file)[i] == NULL)
  1456.                 goto OUT_OF_MEMORY;
  1457.             STRCPY((*file)[i], p->name);
  1458.         }
  1459.         qsort((void *)*file, (size_t)*num_file, sizeof(char_u *), sortcmp);
  1460.     }
  1461. Return:
  1462.     if (domatchend)
  1463.     {
  1464. #ifndef NO_ARP
  1465.         if (dos2)
  1466. #endif
  1467.             MatchEnd(Anchor);
  1468. #ifndef NO_ARP
  1469.         else
  1470.             FreeAnchorChain(Anchor);
  1471. #endif
  1472.     }
  1473.     if (Anchor)
  1474.         free(Anchor);
  1475.     freefiles();
  1476.     if (errmsg)
  1477.     {
  1478.         emsg(errmsg);
  1479.         *num_file = 0;
  1480.         return FAIL;
  1481.     }
  1482.     return OK;
  1483. }
  1484.  
  1485.     void
  1486. FreeWild(num, file)
  1487.     int        num;
  1488.     char_u    **file;
  1489. {
  1490.     if (file == NULL || num == 0)
  1491.         return;
  1492.     while (num--)
  1493.         free(file[num]);
  1494.     free(file);
  1495. }
  1496.  
  1497.     int
  1498. has_wildcard(p)
  1499.     char_u *p;
  1500. {
  1501.     for ( ; *p; ++p)
  1502.         if (strchr("*?[(~#", *p) != NULL)
  1503.             return TRUE;
  1504.     return FALSE;
  1505. }
  1506.  
  1507. /*
  1508.  * With 2.0 support for reading local environment variables
  1509.  * Careful: uses IObuff!
  1510.  */
  1511.  
  1512.     char_u *
  1513. vimgetenv(var)
  1514.     char_u *var;
  1515. {
  1516.     int len;
  1517.  
  1518. #ifndef NO_ARP
  1519.     if (!dos2)
  1520.         return (char_u *)getenv((char *)var);
  1521. #endif
  1522.  
  1523.     len = GetVar((UBYTE *)var, (UBYTE *)IObuff, (long)(IOSIZE - 1), (long)0);
  1524.  
  1525.     if (len == -1)
  1526.         return NULL;
  1527.     else
  1528.         return IObuff;
  1529. }
  1530.